//
//  MCNetworkTool.swift
//  HXWeibo
//
//  Created by HX on 15/11/25.
//  Copyright © 2015年 HX. All rights reserved.
//

import UIKit
import AFNetworking

// MARK: - 网络请求的枚举
enum MCNetworkMethod: String
{
    case GET = "GET"
    case POST = "POST"
}

// 使用枚举统一管理网络错误
enum MCNetworkToolError: Int
{
    case EmptyAccessToken = -1
    case EmptyUid = -2
    
    // 属性，根据不同的枚举类型返回不同的值
    var description: String
        {
            switch self
            {
                case .EmptyAccessToken:
                    return "AccessToken没有值"
                case .EmptyUid:
                    return "Uid没有值"
            }
        }
    // 方法,根据当前类型返回一个NSError
    func error() ->NSError
    {
        return NSError(domain: "cn.itcast.error.net", code: self.rawValue, userInfo: ["description" : self.description])
    }
}

class MCNetworkTool: AFHTTPSessionManager
{
    /// 网络单例
    static let sharedInstance: MCNetworkTool =
    {
        let baseURL = NSURL(string: "https://api.weibo.com/")
        let tool = MCNetworkTool(baseURL: baseURL)
        
        //添加改响应的序列化器
       tool.responseSerializer.acceptableContentTypes?.insert("text/plain")
        
        return tool
    }()
    
    // MARK: - OAuth授权
    /// 申请应用时分配的AppKey
    private let client_id = "3764355848"
    /// 申请应用时分配的AppSecret
    private let client_secret = "2915759ddfd3233af0a3d73cfa9e702b"
    
    ///授权回调地址，站外应用需与设置的回调地址一致，站内应用需填写canvas page的地址
    let redirect_uri = "http://www.baidu.com"
    
    /// 返回授权界面的url地址
    func oauthURL() -> NSURL
    {
        //GET方式拼接登录界面的请求地址
        let urlStr = "https://api.weibo.com/oauth2/authorize?client_id=\(client_id)&redirect_uri=\(redirect_uri)"
        
        return NSURL(string: urlStr)!
    }
    
    //MARK: - 加载AccessToken 只负责加载数据,让别人来处理数据
    func loadAccessToken(code: String, finished: NetworkCallback)
    {
        //https://api.weibo.com/ 这部分定义成baseURL,可以省略
        let urlStr = "oauth2/access_token"
        // 请求参数
        let parameters = ["client_id" : client_id,
                          "client_secret" : client_secret,
                          "grant_type" : "authorization_code",
                          "code" : code,
                          "redirect_uri" : redirect_uri
                          ]
        
        // 发送POST请求 (调用封装好的POST方法)
        request(requestMethod: MCNetworkMethod.POST, urlStr: urlStr, parameters: parameters, needAccessToken: false, finished: finished)
    }
    
    //MARK: - 获取用户数据
    func loadUserInfo(finished: NetworkCallback)
    {
        //https://api.weibo.com/ 这部分定义成baseURL,可以省略
        let urlStr = "2/users/show.json"
       
        // 测试Uid为空
//        MCUserAccount.loadUserAccount()?.uid = nil
        guard let uid = MCUserAccount.loadUserAccount()?.uid else
        {
            //guard 能到这里面来表示uid没有值
            print("uid没有值")
            
            // 通知调用者，没有加载数据，uid没有值
            // 自定义错误，通知调用者
            let error = MCNetworkToolError.EmptyUid.error()
            
            finished(result: nil, error: error)
            
            return
        }

        // 参数
        let parameters = [
            "uid" : uid
        ]
        //发送请求(调用封装好的GET请求)
        request(requestMethod: MCNetworkMethod.GET, urlStr: urlStr, parameters: parameters, needAccessToken: true, finished: finished)
    }
    
    // MARK: - 加载微博数据
    //要实现下拉刷新，需要传入since_id参数
    //要实现上拉加载更多数据，需要传入max_id参数
    func loadStatus(since_id: Int, max_id: Int, finished: NetworkCallback)
    {//通过闭包告诉调用者，网络请求成功还是失败
        // url https://api.weibo.com/ 这部分定义成baseURL,可以省略
        let urlStr = "2/statuses/home_timeline.json"
        
        //参数
        var parameters = [String : AnyObject]()
        
        // 拼接参数
        if since_id > 0//下拉刷新
        {
            parameters["since_id"] = since_id
        }
        else if max_id > 0//上拉加载更多
        {
            parameters["max_id"] = max_id
        }
        
        // 调用封装好的GET请求
        let debug = false
        if debug
        {
            // 如果是调试，就加载本地数据
            loadLocalStatuses(finished)
        }
        else
        {// 不是调试，加载网络微博数据
            request(requestMethod: MCNetworkMethod.GET, urlStr: urlStr, parameters: parameters, needAccessToken: true, finished: finished)
        }
    }
    
    // MARK: - 加载本地微博数据(用来测试的)
    private func loadLocalStatuses(finished: NetworkCallback)
    {
        // 获取测试微博数路径
        let path = NSBundle.mainBundle().pathForResource("statuses", ofType: "json")!
        
        let data = NSData(contentsOfFile: path)!
        
        // 将NSData转换成JSON
        // TRY! 强制try 如果JSONObjectWithData出现异常，程序直接崩溃
        do
        {
            let json = try? NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions(rawValue: 0))
            
            // 通知调用者 获取到了本地数据
            finished(result: json as? [String: AnyObject], error: nil)
        }
        catch
        {
            print("出现异常")
        }
    }
    
    // MARK: - 定义闭包类型别名
    typealias NetworkCallback = (result: [String: AnyObject]?, error: NSError?) -> ()
    
    // MARK: - 抽取AFN GET / POST 方法
    func request(requestMethod requestMethod: MCNetworkMethod, urlStr: String, var parameters: [String: AnyObject], needAccessToken: Bool, finished: NetworkCallback)
    {
        // 如果需要AccessToken，就拼接一个
        if needAccessToken
        {
            guard let access_token = MCUserAccount.loadUserAccount()?.access_token else
            {
                print("进来这里就代表access_token没有值")
                
                let error = MCNetworkToolError.EmptyAccessToken.error()
                
                finished(result: nil, error: error)
                
                return
            }
            // 拼接access_token
            parameters["access_token"] = access_token
        }
        
        // 准备成功的闭包
        let successCallback = { (task: NSURLSessionDataTask, result: AnyObject) -> Void in
            
            // 执行的代码
            finished(result: result as? [String: AnyObject], error: nil)
        }
        // 准备失败的闭包
        let failureCallback = { (task: NSURLSessionDataTask?, error: NSError) -> Void in
            
            finished(result: nil, error: error)
        }
        
        // 根据请求方法，发送对应的请求
        switch requestMethod
        {
        case .GET:
            GET(urlStr, parameters: parameters, success: successCallback, failure: failureCallback)
            
        case .POST:
            POST(urlStr, parameters: parameters, success: successCallback, failure: failureCallback)
        }
    }
}

































